<?php
namespace addons\ymypaypal\services;
use fast\Random;
use PayPal\Api\Currency;
use PayPal\Api\VerifyWebhookSignature;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Exception\PayPalConnectionException;
use PayPal\Rest\ApiContext;
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Api\PaymentExecution;
use think\exception\HttpException;
use think\Log;
use think\Request;

class PayPalService
{
    /*
         * array
         */
    protected $config;

    /*
     * string
     */
    protected $notifyWebHookId;

    /*
     * obj ApiContext
     */
    public $apiContext;

    public function __construct($config = false)
    {
        if(!$config){
            $config = get_addon_config('ymypaypal');
        }
        // 密钥配置
        $this->config = $config;


        $this->apiContext = new ApiContext(
            new OAuthTokenCredential(
                $this->config['client_id'],
                $this->config['secret']
            )
        );

        $this->apiContext->setConfig([
            'mode' => $this->config['mode'],
            'log.LogEnabled' => true,
            'log.FileName' => ROOT_PATH . '/runtime/log/PayPal.log',
            'log.LogLevel' => 'DEBUG', // PLEASE USE `INFO` LEVEL FOR LOGGING IN LIVE ENVIRONMENTS
            'cache.enabled' => true,
        ]);

    }

    /**
     * @Des 收银台支付
     * @Author Mars
     * @param Order $order
     * @return string|null
     */
    public function checkout($pay,$currency)
    {
        try {
            $currency = $currency ?? 'AUD';
            // 交易号
            $pay_no = [];
            // 订单号
            $order_no = [];
            // 付款金额
            $price = 0;
            $rmb_price = 0;
            // 订单列表
            $order_list = [];
            foreach($pay as $row){
                // 总价格
                $price += $row['price'];
                $rmb_price += $row['rmb_price'];
                // 订单集
                $order_no[] = $row['order_no'];
                // 交易集
                $pay_no[] = $row['pay_no'];
                $order_list[] = model('app\api\model\wanlshop\Order')->get($row['order_id'],['goods','pay']);
            }
            $pay_no = implode(',',$pay_no);

            $payer = new Payer();
            $payer->setPaymentMethod('paypal');
            $transactions = [];
            foreach ($order_list as $order){

                $items = [];

                //循环订单商品
                foreach ($order['goods'] as $goods){
                    $item = new Item();
                    $item->setName($goods['title']) // 子订单的名称 如 $order->goods->title
                    ->setDescription($goods['difference']) // 子订单描述 如 $order->order_no
                    ->setCurrency($currency) // 币种  如 $order->currency
                    ->setQuantity($goods['number']) // 数量 如 $order->goods->num
                    ->setPrice($goods['price']); // 价格 如 $order->goods->total_amount
                    $items[] = $item;
                }

                $itemList = new ItemList();
                $itemList->setItems($items); // 设置子订单列表
                // 这里是设置运费等
                $details = new Details();
                $details->setShipping($order['pay']['freight_price']) // 运费
                ->setSubtotal($order['pay']['order_price']); // 支付金额
                // 设置总计费用
                $amount = new Amount();
                $amount->setCurrency($currency) // 币种
                ->setTotal($order['pay']['price']) // 支付金额
                ->setDetails($details);
                // 创建交易
                $transaction = new Transaction();
                $transaction->setAmount($amount)
                    ->setItemList($itemList)
                    ->setDescription($order['order_no']) // 订单描述 如 $order->order_no
                    ->setInvoiceNumber($order['pay']['pay_no']); // 订单号 如 $order->order_no
                $transactions[] = $transaction;
            }

             // 这里设置支付成功和失败后的跳转链接
            $redirectUrls = new RedirectUrls();
            $redirectUrls->setReturnUrl(addon_url('ymypaypal/index/return',['success'=>'true','pay_no'=>$pay_no],true,true))
                ->setCancelUrl(addon_url('ymypaypal/index/return',['success'=>'false','pay_no'=>$pay_no],true,true));

            $payment = new Payment();
            $payment->setIntent('sale')
                ->setPayer($payer)
                ->setRedirectUrls($redirectUrls)
                ->setTransactions($transactions);

            $payment->create($this->apiContext);

            // 得到支付链接
            return $payment->getApprovalLink();
        } catch (HttpException $e) {
            Log::error('PayPal Checkout Create Failed'.json_encode(['msg' => $e->getMessage(), 'code' => $e->getStatusCode(), 'data' => ['order' => ['no' => $order_no]]]));

            return false;
        } catch (PayPalConnectionException $e) {
            $res = $e->getData();
            Log::error('PayPal Checkout Create Failed'.$res);
        }
    }

    /**
     * @Des 执行付款
     * @Author Mars
     * @param Payment $payment
     * @return bool|Payment
     */
    public function executePayment($paymentId)
    {
        try {
            $payment = Payment::get($paymentId, $this->apiContext);

            $execution = new PaymentExecution();
            $execution->setPayerId($payment->getPayer()->getPayerInfo()->getPayerId());

            // 执行付款
            $payment->execute($execution, $this->apiContext);
            return Payment::get($payment->getId(), $this->apiContext);
        } catch (HttpException $e) {
            return false;
        }
    }

    //获取payment
    public function getPayment($paymentId)
    {
        try {
            $payment = Payment::get($paymentId, $this->apiContext);

            return $payment;
        } catch (HttpException $e) {
            return false;
        }
    }

    /**
     * @des 回调验签
     * @author Mars
     * @param Request $request
     * @param $webHookId
     * @return VerifyWebhookSignature|bool
     */
    public function verify(Request $request, $webHookId = null)
    {
        try {
            $headers = $request->header();
            $headers = array_change_key_case($headers, CASE_UPPER);
            $content = $request->getContent();
            $signatureVerification = new VerifyWebhookSignature();
            $signatureVerification->setAuthAlgo($headers['PAYPAL-AUTH-ALGO']);
            $signatureVerification->setTransmissionId($headers['PAYPAL-TRANSMISSION-ID']);
            $signatureVerification->setCertUrl($headers['PAYPAL-CERT-URL']);
            $signatureVerification->setWebhookId($webHookId ?: $this->notifyWebHookId);
            $signatureVerification->setTransmissionSig($headers['PAYPAL-TRANSMISSION-SIG']);
            $signatureVerification->setTransmissionTime($headers['PAYPAL-TRANSMISSION-TIME']);
            $signatureVerification->setRequestBody($content);

            $result = clone $signatureVerification;
            $output = $signatureVerification->post($this->apiContext);
            if ($output->getVerificationStatus() == "SUCCESS") {
                return $result;
            }
            throw new HttpException(400, 'Verify Failed.');
        } catch (HttpException $e) {
            Log::error('PayPal Notification Verify Failed' . json_encode( ['msg' => $e->getMessage(), 'code' => $e->getStatusCode(), 'data' => ['request' => ['header' => $headers, 'body' => $content]]]));
            return false;
        }
    }


}